﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Linq;
using System.Reflection;

namespace XiaoSe.Data
{
    /// <summary>
    /// 模型帮助类
    /// </summary>
    public class ModelHelper
    {
        public List<T> DataReaderToList<T>(DbDataReader reader) where T : new()
        {
            var listT = new List<T>();
            var piList = typeof(T).GetProperties();
            while (reader.Read())
            {
                var model = new T();
                foreach (var p in piList)
                {
                    if (null != reader[p.Name] && DBNull.Value != reader[p.Name])
                    {
                        p.SetValue(model, reader[p.Name], null);
                    }
                }
                listT.Add(model);
            }
            return listT;
        }
        public List<T> DataTableToList<T>(DataTable table) where T : new()
        {
            var listT = new List<T>();
            var list = typeof(T).GetProperties();
            for (var i = 0; i < table.Rows.Count; i++)
            {
                var model = new T();
                foreach (var p in list)
                {
                    if (table.Rows[i][p.Name] != DBNull.Value)
                    {
                        p.SetValue(model, table.Rows[i][p.Name], null);
                    }
                }
                listT.Add(model);
            }
            return listT;
        }
        public SqlParameter[] ModelToSqlParameter<T>(T model, CreateSqlText cs, string removeField, ref string sqlInsertText, string paramEx)
        {
            removeField = removeField.ToLower();
            int iFieldCount = 0;
            var piList = typeof(T).GetProperties();
            if (cs == CreateSqlText.CreateInsert || cs == CreateSqlText.CreateUpdate)
            {
                if (cs == CreateSqlText.CreateInsert)
                    iFieldCount = ModelGetSqlInsertText(model, removeField, ref sqlInsertText, paramEx);
                if (cs == CreateSqlText.CreateUpdate)
                    iFieldCount = ModelGetSqlUpdateText(model, removeField, ref sqlInsertText, paramEx);
            }
            else
            {
                iFieldCount += piList.Count(p => !removeField.Contains("," + p.Name.ToLower() + ","));
            }
            var spList = new SqlParameter[iFieldCount];
            var iFieldIndex = 0;
            foreach (var p in piList)
            {
                if (removeField.Contains("," + p.Name.ToLower() + ",")) continue;
                var sp = new SqlParameter {ParameterName = "@" + p.Name + paramEx, Value = p.GetValue(model, null)};
                spList[iFieldIndex] = sp;
                iFieldIndex++;
            }
            foreach (SqlParameter p in spList)
            {
                if (p.Value == null)
                {
                    p.Value = DBNull.Value;
                }
            }
            return spList;
        }
        public int ModelGetSqlInsertText<T>(T model, string removeField, ref string sqlInsertText, string paramEx)
        {
            if (sqlInsertText == null) throw new ArgumentNullException("sqlInsertText");
            removeField = removeField.ToLower();
            var iFieldCount = 0;
            sqlInsertText = "insert into [" + typeof(T).Name + "] (";
            PropertyInfo[] piList = typeof(T).GetProperties();
            foreach (PropertyInfo p in piList)
            {
                if (!removeField.Contains("," + p.Name.ToLower() + ","))
                {
                    sqlInsertText += "[";
                    sqlInsertText += p.Name;
                    sqlInsertText += "],";
                    iFieldCount++;
                }
            }
            sqlInsertText = sqlInsertText.TrimEnd(',');
            sqlInsertText += ")values(";
            sqlInsertText = piList.Where(p => !removeField.Contains("," + p.Name.ToLower() + ",")).Aggregate(sqlInsertText, (current, p) => current + ("@" + p.Name + paramEx + ","));
            sqlInsertText = sqlInsertText.TrimEnd(',');
            sqlInsertText += ");select @@IDENTITY";
            return iFieldCount;
        }
        public int ModelGetSqlUpdateText<T>(T model, string removeField, ref string sqlInsertText, string paramEx)
        {
            if (sqlInsertText == null) throw new ArgumentNullException("sqlInsertText");
            removeField = removeField.ToLower();
            var iFieldCount = 0;
            sqlInsertText = "update [" + typeof(T).Name + "] set";
            var piList = typeof(T).GetProperties();
            foreach (var p in piList)
            {
                if (removeField.Contains("," + p.Name.ToLower() + ",")) continue;
                sqlInsertText += "[";
                sqlInsertText += p.Name;
                sqlInsertText += "]=";
                sqlInsertText += "@" + p.Name + paramEx + ",";
                iFieldCount++;
            }
            sqlInsertText = sqlInsertText.TrimEnd(',');
            return iFieldCount;
        }
    }
    public enum CreateSqlText
    {
        None = 0,
        CreateInsert = 1,
        CreateUpdate = 2
    }
}
